<template>
<div class="virtual">
  <div class="scroll-container" ref="scrollContainer" @scroll.passive="handleScroll">
    <div :style="{paddingTop: topBlankFill + 'px',paddingBottom: bottomBlankFill + 'px'}">
      <div class="scroll-list" v-for="(item,index) in visibleList" :key="item.id" :id="item.id">
        <div class="img">
          <img :src="item.uri" alt="">
        </div>
        <div class="message">
          <span>{{item.message}}</span>
        </div>
      </div>
      <div class="pulling" v-if="isRequestStatus">
        <span>数据正在加载中......</span>
      </div>
    </div>
  </div>
</div>
</template>

<script>
import message from '../../../public/data/message.json';
import imgs from '../../../public/data/imgs.json'
function getItem() {
  const index = Math.floor(Math.random() * imgs.length);
  return {...imgs[index],message: message[index]}
}

export default {
  name: "Virtual",
  data() {
    return {
      pageNum: 0,
      listData: [],
      oneHeight: 130, // 单条数据的高度
      startIndex: 0, // 当前可见视图中的第一个元素的索引
      visibleNumber: 0, // 当前可见视图内展示数据的条数
      isRequestStatus: true, // 是否在上拉加载
      isScrollStatus: true, // 滚动节流优化
    }
  },
  computed: {
    // 计算可见视图中最后一个视图的索引
    endIndex () {
      let endIndex = this.startIndex + this.visibleNumber
      if (endIndex === this.listData.length) {
        endIndex = this.listData.length;
      }
      return endIndex;
    },
    // 当前可见视图内需要展示数据
    visibleList() {
      // console.log(this.startIndex,this.endIndex);
      return this.listData.slice(this.startIndex,this.endIndex);
    },
    // 计算上留白的高度
    topBlankFill() {
      return this.startIndex * this.oneHeight
    },
    // 计算下留白的高度
    bottomBlankFill() {
      const pb = (this.listData.length - this.endIndex)*this.oneHeight;
      if (pb < 0) {
        return 0;
      }
      return pb;
    }
  },
  created() {
    this.fetch(30).then((res) => {
      this.listData = [...res];
      this.isRequestStatus = false
      console.log(this.listData);
    })
  },
  mounted() {
    // 计算当前视图中可见元素的个数
    this.visibleNumber = Math.floor(this.$refs.scrollContainer.offsetHeight / this.oneHeight) + 2;
  },
  methods:{
    fetch(count) {
      count = count || 30;
      return new Promise((resolve,reject) => {
        setTimeout(() => {
          if (++this.pageNum > 30) {
            resolve(false)
          } else {
            let items = []
            for (let i = 0; i < count; i++) {
              items[i] = {id: i + 1,...getItem(),}
            }
            resolve(items)
          }
        }, 3000)
      })
    },
    // 滚动计算
    handleScroll() {
      // 计算当前视图中第一个元素的索引
      const currentIndex = ~~(this.$refs.scrollContainer.scrollTop / this.oneHeight); // 优化滚动计算效率
      if (this.startIndex === currentIndex) return
      this.startIndex = currentIndex
      // 计算是否滚动到屏幕底部
      if (this.startIndex + this.visibleNumber === this.listData.length -1 && !this.isRequestStatus) {
        console.log(123);
        this.isRequestStatus = true
        this.fetch(30).then((res) => {
          this.isRequestStatus = false
          this.listData = [...this.listData,...res];
          console.log(this.listData);
        })
      }
    },
  }
}
</script>

<style scoped lang="less">
@import "./Virtual.less";
</style>
